package com.starlink.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.hutool.core.convert.Convert;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.PageHelper;
import com.starlink.common.domain.BaseEntity;
import com.starlink.model.domain.*;
import com.starlink.model.request.SchoolbagPhaseBooksRequest;
import com.starlink.model.request.SchoolbagPhaseRequest;
import com.starlink.model.vo.SchoolbagPhaseVO;
import com.starlink.service.*;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.data.domain.Pageable;
import com.starlink.common.utils.AssertUtil;
import com.starlink.model.dtomapper.SchoolbagSpecificationDtoMapper;
import com.starlink.mapper.SchoolbagSpecificationMapper;
import com.starlink.model.request.SchoolbagSpecificationRequest;
import com.starlink.model.util.SchoolbagSpecificationConvert;
import com.starlink.model.vo.SchoolbagSpecificationVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static com.starlink.utils.PageUtils.getOrderBy;

import java.util.List;
import java.util.Objects;

/**
 * @author zhanghong
 */
@Service
public class SchoolbagSpecificationServiceImpl extends ServiceImpl<SchoolbagSpecificationMapper, SchoolbagSpecificationDO> implements SchoolbagSpecificationService {
    @Autowired
    private SchoolbagSpecificationMapper schoolbagSpecificationMapper;
    @Autowired
    private SchoolbagService schoolbagService;
    @Autowired
    private SchoolbagPhaseService schoolbagPhaseService;
    @Autowired
    private SchoolbagPhaseBooksService schoolbagPhaseBooksService;
    @Autowired
    private SchoolbagGroupService schoolbagGroupService;

    @Override
    public SchoolbagSpecificationVO getByKey(long id) {
        SchoolbagSpecificationVO schoolbagSpecificationVO = SchoolbagSpecificationDtoMapper.INSTANCE.do2VO(getById(id));
        SchoolbagPhaseRequest request = new SchoolbagPhaseRequest();
        request.setCategoryId(schoolbagSpecificationVO.getSchoolbagId());
        request.setSpecId(schoolbagSpecificationVO.getId());
        List<SchoolbagPhaseVO> phases = schoolbagPhaseService.listQuery(request);
        for (SchoolbagPhaseVO phase : phases) {
            SchoolbagPhaseBooksRequest booksRequest = new SchoolbagPhaseBooksRequest();
            booksRequest.setCategoryId(schoolbagSpecificationVO.getSchoolbagId());
            booksRequest.setSpecId(schoolbagSpecificationVO.getId());
            booksRequest.setPhaseId(phase.getId());
            phase.setPhaseBooks(schoolbagPhaseBooksService.listQuery(booksRequest));
        }
        schoolbagSpecificationVO.setPhases(phases);
        return schoolbagSpecificationVO;
    }

    @Override
    public PageInfo<SchoolbagSpecificationVO> pageQuery(Pageable pageable, SchoolbagSpecificationRequest request) {
        PageHelper.startPage(pageable.getPageNumber(), pageable.getPageSize(), getOrderBy(pageable.getSort())).setReasonable(true);
        List<SchoolbagSpecificationDO> list = schoolbagSpecificationMapper.listQuery(request);
        List<SchoolbagSpecificationVO> schoolbagSpecificationVOList = SchoolbagSpecificationConvert.buildSchoolbagSpecificationVoList(list);
        return new PageInfo(schoolbagSpecificationVOList);
    }

    @Override
    public List<SchoolbagSpecificationVO> listQuery(SchoolbagSpecificationRequest request) {
        List<SchoolbagSpecificationDO> list = schoolbagSpecificationMapper.selectDOList(SchoolbagSpecificationDtoMapper.INSTANCE.request2DO(request));
        List<SchoolbagSpecificationVO> schoolbagSpecificationVOS = SchoolbagSpecificationConvert.buildSchoolbagSpecificationVoList(list);
        return schoolbagSpecificationVOS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(SchoolbagSpecificationRequest request) {
        // 校验
        AssertUtil.assertNotNull(request.getSchoolbagId(), "书包id不能为空");
        SchoolbagDO schoolbagDO = schoolbagService.lambdaQuery()
                .eq(BaseEntity::getId, request.getSchoolbagId())
                .last("limit 1")
                .one();
        AssertUtil.assertNotNull(schoolbagDO, "书包不存在");

        AssertUtil.assertNotNull(request.getSpecName(), "规格名称不能为空");
        AssertUtil.assertNotEmpty(request.getPhases(), "分期书单集合不能为空");
        AssertUtil.assertTrue(request.getPhases().size() == 12, "分数书单必须为12期");
        for (SchoolbagPhaseRequest phase : request.getPhases()) {
            AssertUtil.assertNotEmpty(phase.getPhaseBooks(), "每一期的书单不能为空");
            // TODO MOCK 不校验书本的数量（测试时只有一本书）
//            AssertUtil.assertTrue(phase.getPhaseBooks().size() == Integer.parseInt(schoolbagDO.getSpecification()), String.format("每一期的书单的应该为%s本", schoolbagDO.getSpecification()));
        }

        SchoolbagSpecificationDO specificationDO = lambdaQuery()
                .eq(SchoolbagSpecificationDO::getSchoolbagId, request.getSchoolbagId())
                .eq(SchoolbagSpecificationDO::getSpecName, request.getSpecName())
                .last("limit 1")
                .one();
        AssertUtil.assertNull(specificationDO, "规格已存在");
        SchoolbagSpecificationDO spec = SchoolbagSpecificationDtoMapper.INSTANCE.request2DO(request);
        if (save(spec)) {
            // 分期书单
            Integer phaseNum = 1;
            for (SchoolbagPhaseRequest phaseRequest : request.getPhases()) {
                AssertUtil.assertNotNull(phaseRequest.getPhaseBooks(), "书单书籍不能为空");
                phaseRequest.setCategoryId(schoolbagDO.getId());
                phaseRequest.setSpecId(spec.getId());
                phaseRequest.setPhaseNum(phaseNum);
                if (schoolbagPhaseService.add(phaseRequest)) {
                    List<SchoolbagPhaseBooksRequest> phaseBooks = phaseRequest.getPhaseBooks();
                    // 分期书单书籍
                    for (SchoolbagPhaseBooksRequest phaseBooksRequest : phaseBooks) {
                        phaseBooksRequest.setId(null);
                        phaseBooksRequest.setCategoryId(schoolbagDO.getId());
                        phaseBooksRequest.setSpecId(spec.getId());
                        phaseBooksRequest.setPhaseId(phaseRequest.getId());
                        schoolbagPhaseBooksService.add(phaseBooksRequest);
                    }
                }
                phaseNum = phaseNum + 1;
            }
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByKey(SchoolbagSpecificationRequest request) {
        AssertUtil.assertNotNull(request.getId(), "id不能为空");
        SchoolbagSpecificationDO specificationDO = schoolbagSpecificationMapper.selectDOById(request.getId());
        AssertUtil.assertNotNull(specificationDO, "规格不存在");
        if (saveOrUpdate(SchoolbagSpecificationDtoMapper.INSTANCE.request2DO(request)) && CollectionUtils.isNotEmpty(request.getPhases())) {
            // 先删后新增
            schoolbagPhaseService.lambdaUpdate().eq(SchoolbagPhaseDO::getCategoryId, specificationDO.getSchoolbagId()).remove();
            schoolbagPhaseBooksService.lambdaUpdate().eq(SchoolbagPhaseBooksDO::getCategoryId, specificationDO.getSchoolbagId()).remove();

            // 分期书单
            Integer phaseNum = 1;
            for (SchoolbagPhaseRequest phaseRequest : request.getPhases()) {
                AssertUtil.assertNotNull(phaseRequest.getPhaseBooks(), "书单书籍不能为空");
                phaseRequest.setCategoryId(specificationDO.getSchoolbagId());
                phaseRequest.setSpecId(specificationDO.getId());
                phaseRequest.setPhaseNum(phaseNum);
                if (schoolbagPhaseService.add(phaseRequest)) {
                    List<SchoolbagPhaseBooksRequest> phaseBooks = phaseRequest.getPhaseBooks();
                    // 分期书单书籍
                    for (SchoolbagPhaseBooksRequest phaseBooksRequest : phaseBooks) {
                        phaseBooksRequest.setCategoryId(specificationDO.getSchoolbagId());
                        phaseBooksRequest.setSpecId(specificationDO.getId());
                        phaseBooksRequest.setPhaseId(phaseRequest.getId());
                        schoolbagPhaseBooksService.add(phaseBooksRequest);
                    }
                }
                phaseNum = phaseNum + 1;
            }
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteDOByIds(String ids) {
        for (String id : Convert.toStrArray(ids)) {
            Long count = schoolbagGroupService.lambdaQuery().eq(SchoolbagGroupDO::getSpecId, id).count();
            AssertUtil.assertTrue(Objects.equals(count, 0L), "该规则下有分组，不能删除");
        }
        schoolbagSpecificationMapper.deleteDOByIds(Convert.toStrArray(ids));
        return true;
    }
}
